package com.milhouz.findmydroid.bean;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;

import com.milhouz.findmydroid.db.AppConstants;
import com.milhouz.findmydroid.exception.EndOfCharacterListException;
import com.milhouz.findmydroid.exception.EndOfGameException;

public class Game implements Parcelable {

	/* Constants */
	final static int MIN_TEAMS = 2;
	final static int MAX_TEAMS = 6;
	final static int MIN_TIME = 20;
	final static int MAX_TIME = 60;
	final static int MIN_CARDS = 20;
	final static int MAX_CARDS = 100;

	/* Game settings */
	int nbTeams = MIN_TEAMS;
	long time = 30;
	int nbCards = 40;
	List<String> categories = new ArrayList<String>();
	boolean isCustomCharacter = false;

	/* Characters */
	List<Character> characters = new LinkedList<Character>();
	int currentCharacterId = 0;

	/* Teams playing */
	List<Team> teams = new ArrayList<Team>();
	int currentTeamIndex = 0;

	/* Game modes */
	GameMode gameMode = GameMode.DESCRIBE_MODE;

	public enum GameMode {
		DESCRIBE_MODE, ONEWORD_MODE, MIME_MODE
	}

	public Game() {
	}

	public void initGame() {
		this.teams.clear();
		for (int i = 0; i < this.nbTeams; i++) {
			this.teams.add(new Team(i + 1));
		}
	}

	public void shuffleCharacters() {
		currentCharacterId = 0;
		Collections.shuffle(characters);
	}

	public Team getWinner() {
		Team winner = null;
		for (Team team : teams) {
			if (winner == null || team.getNbPoints() > winner.getNbPoints()) {
				winner = team;
			}
		}
		return winner;
	}

	public Team getCurrentTeam() {
		return teams.get(currentTeamIndex);
	}

	public Team getNextTeam() {
		if (this.currentTeamIndex == (this.nbTeams - 1)) {
			this.currentTeamIndex = 0;
		} else {
			this.currentTeamIndex++;
		}
		return getCurrentTeam();
	}

	public GameMode getGameMode() {
		return gameMode;
	}

	public void setNextTeam() {
		if (this.nbTeams >= MAX_TEAMS) {
			this.nbTeams = MIN_TEAMS;
		} else {
			this.nbTeams++;
		}
	}

	public void setNextTime() {
		if (this.time >= MAX_TIME) {
			this.time = MIN_TIME;
		} else {
			this.time += 10;
		}
	}

	public void setNextNbCards() {
		if (this.nbCards >= MAX_CARDS) {
			this.nbCards = MIN_CARDS;
		} else {
			this.nbCards += 10;
		}
	}

	public void setNextGameMode() throws EndOfGameException {
		switch (gameMode) {
		case DESCRIBE_MODE:
			gameMode = GameMode.ONEWORD_MODE;
			break;
		case ONEWORD_MODE:
			gameMode = GameMode.MIME_MODE;
			break;
		case MIME_MODE:
			throw new EndOfGameException();
		}
	}

	public int getNbTeams() {
		return nbTeams;
	}

	public long getTime() {
		return time;
	}

	public int getNbCards() {
		return nbCards;
	}

	public List<String> getCategories() {
		return categories;
	}

	public void setNbTeams(int nbTeams) {
		this.nbTeams = nbTeams;
	}

	public List<Character> getCharacters() {
		return characters;
	}

	public int getCurrentCharacterId() {
		return currentCharacterId;
	}

	public Character getCurrentCharacter() {
		Log.i(AppConstants.TAG, "" + currentCharacterId);
		return characters.get(currentCharacterId);
	}

	public Character getNextCharacter() throws EndOfCharacterListException {
		if (currentCharacterId < nbCards - 1) {
			currentCharacterId++;
		} else {
			throw new EndOfCharacterListException();
		}
		return getCurrentCharacter();
	}

	public Character getPreviousCharacter() {
		if (currentCharacterId > 0) {
			currentCharacterId--;
		}
		return getCurrentCharacter();
	}

	public List<Team> getTeams() {
		return teams;
	}

	public boolean isCustomCharacter() {
		return isCustomCharacter;
	}

	public void setCustomCharacter(boolean isCustomCharacter) {
		this.isCustomCharacter = isCustomCharacter;
	}

	@Override
	public void writeToParcel(Parcel parcel, int flags) {
		parcel.writeInt(nbTeams);
		parcel.writeLong(time);
		parcel.writeInt(nbCards);
		parcel.writeString(String.valueOf(gameMode));
		parcel.writeString(String.valueOf(isCustomCharacter));
		parcel.writeList(characters);
	}

	public static final Creator<Game> CREATOR = new Creator<Game>() {
		@SuppressWarnings("unchecked")
		@Override
		public Game createFromParcel(Parcel source) {
			Game g = new Game();
			g.nbTeams = source.readInt();
			g.time = source.readLong();
			g.nbCards = source.readInt();
			g.gameMode = GameMode.valueOf(source.readString());
			g.isCustomCharacter = Boolean.valueOf(source.readString());
			g.characters = source.readArrayList(Character.class.getClassLoader());
			return g;
		}

		@Override
		public Game[] newArray(int arg0) {
			return null;
		}
	};

	@Override
	public int describeContents() {
		return 0;
	}

	@Override
	public String toString() {
		return "Game [time=" + time + ", nbTeams=" + nbTeams + ", nbCards=" + nbCards + ", gameMode=" + gameMode + "]";
	}

}